<template>
  <div :style="{position: 'absolute', 'z-index': zIndex, width: maxCanvasInfo.width + 'px', height: maxCanvasInfo.height + 'px'}">
    <div class="contain" :style="getContain">
      <div class="wrap-box" :style="getWrapBox">
        <div class="canvas">
          <img :src="imgUrl" class="canvas-hide" :style="{transform: `scale(${imgInfo.flipX ? -1 : 1},${imgInfo.flipY ? -1 : 1})`}"/>
        </div>
      </div>

      <div class="crop-box" :style="getStyle(imgData.cropBox)" @mousedown.stop.prevent="handleDown">
        <span class="view-box" @mousedown.stop.prevent="handleCanvasDown">
          <img v-if="false"  :src="imgUrl" :style="getWrapBox" />
        </span>
        <span v-show="showLine" class="dashed dashed-h" />
        <span v-show="showLine" class="dashed dashed-v" />
        <span class="face move" data-cropper-action="move" />
        <span class="line line-e" data-cropper-action="e" />
        <span class="line line-n" data-cropper-action="n" />
        <span class="line line-w" data-cropper-action="w" />
        <span class="line line-s" data-cropper-action="s" />
        <span class="longer longer-e" data-cropper-action="e" />
        <span class="longer longer-n" data-cropper-action="n" />
        <span class="longer longer-w" data-cropper-action="w" />
        <span class="longer longer-s" data-cropper-action="s" />
        <span v-show="!showLine" class="point point-ne" data-cropper-action="ne" />
        <span v-show="!showLine" class="point point-nw" data-cropper-action="nw" />
        <span v-show="!showLine" class="point point-sw" data-cropper-action="sw" />
        <span v-show="!showLine" class="point point-se" data-cropper-action="se" />
      </div>
    </div>
  </div>

</template>

<script>
export default {
  name: 'Cropper',
  props: {
    parentId: {
      type: String,
      default: 'edit'
    },
    imgUrl: {
      type: String,
      default: ''
    },
    zIndex: {
      type: Number,
      default: 999
    },
    cropperInfo: {
      type: Object,
      default: () => {
        return {
          left: 0,
          top: 0,
          width: 0,
          height: 0
        }
      }
    },
    imgInfo: {
      type: Object,
      default: () => {
        return {
          left: 0,
          top: 0,
          width: 0,
          height: 0,
          scaleX: 1,
          scaleY: 1,
          flipX: false,
          flipY: false
        }
      }
    },
    // false 非等比的。 true 等比
    type: {
      type: Boolean,
      default: false
    },
    // 非等比的情况下 该参数有效
    maxCanvasInfo: {
      type: Object,
      default: () => {
        return {
          width: 600,
          height: 600
        }
      }
    },
    // 定义 等比缩放情况下，x y 的比例值
    equalRatio: {
      type: Object,
      default: () => {
        return {
          x: 1,
          y: 1
        }
      }
    },
    imgRotate: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      minVal: 20,
      rotate: 0,
      imgData: {
        contain: {
          width: 0,
          height: 0,
          left: 0,
          top: 0
        },
        canvas: {
          left: 0,
          top: 0,
          width: 0,
          height: 0,
          flipX: false,
          flipY: false
        },
        cropBox: {
          left: 0,
          top: 0,
          width: 0,
          height: 0
        },
        // 代表图片的宽高
        img: {
          w: 0,
          h: 0
        }
      },
      tooltipStyle: {
        top: -40,
        left: 0
      },
      showLine: false,
      pagePosition: {},
      rotateScale: 1,
      moveRect: {
        minX: 0,
        minY: 0,
        maxX: 0,
        maxY: 0
      },
      // 代表的是旋转后的图片信息 x y 旋转后的中心
      showRect: {
        x: 0,
        y: 0,
        w: 0,
        h: 0,
        r: 0,
        sv: 0, // 垂直翻转
        sH: 0 // 水平翻转
      },
      // 代表裁剪框的大小 x y 裁剪框的？？？
      maskRect: {
        x: 0,
        y: 0,
        w: 0,
        h: 0,
        oldX: 0,
        oldY: 0
      }
    }
  },
  computed: {
    getContain() {
      return {
        ...this.getStyle(this.imgData.contain),
        top: this.imgData.contain.top + 'px',
        left: this.imgData.contain.left + 'px',
        transform: `rotate(0deg)`
      }
    },
    getWrapBox() {
      const { left, top, width, height } = this.imgData.canvas
      return {
        width: width + 'px',
        height: height + 'px',
        transform: `translate(${left}px, ${top}px) rotate(${this.imgRotate}deg)`
      }
    }
  },
  watch: {
    imgRotate() {
      this.updateMoveRect()
      const newData = this.checkRange()
      this.updateShowRect({ left: newData[0], top: newData[1], width: newData[2], height: newData[3] })
    },
    showRect: {
      handler({ x, y, w, h }) {
        // console.log(x, y, w, h, 'showRect')
        this.imgData.canvas.width = w
        this.imgData.canvas.height = h
        const newPoint = this.rotatePoint(x, y, -this.imgRotate)
        this.imgData.canvas.left = newPoint.x - w / 2 + this.imgData.cropBox.width / 2
        this.imgData.canvas.top = newPoint.y - h / 2 + this.imgData.cropBox.height / 2

        this.handleCropper()
      },
      deep: true
    },
    maskRect: {
      handler({ x, y, w, h, oldX, oldY }) {
        // console.log(x, y, 'width: ' + w, 'height: ' + h, oldX, oldY, 'maskRect')
        this.imgData.cropBox.left += x - oldX
        this.imgData.cropBox.top += y - oldY
        this.imgData.cropBox.width = w
        this.imgData.cropBox.height = h
      },
      deep: true
    }
  },
  mounted() {
    // this.setImgData()
  },
  methods: {
    /**
     * 取消（false）和确定（true）
     * */
    handleCropper(state = true) {
      let newCropperInfo = {
        left: this.cropperInfo.left,
        top: this.cropperInfo.top,
        width: this.cropperInfo.width,
        height: this.cropperInfo.height,
        rotate: this.imgRotate,
        imgInfo: {
          left: this.imgInfo.left,
          top: this.imgInfo.top,
          width: this.imgInfo.width,
          height: this.imgInfo.height,
          scaleX: this.imgInfo.scaleX,
          scaleY: this.imgInfo.scaleY
        }
      }
      if (state) {
        newCropperInfo = {
          imgInfo: {
            left: this.imgData.canvas.left,
            top: this.imgData.canvas.top,
            width: this.imgData.canvas.width / this.imgInfo.scaleX,
            height: this.imgData.canvas.height / this.imgInfo.scaleY,
            scaleX: this.imgInfo.scaleX,
            scaleY: this.imgInfo.scaleY
          }
        }
      }
      this.$emit('handleCropper', newCropperInfo)
    },
    /**
     * 重置
     * */
    resetCropper() {
      this.setImgData()
    },
    /**
     * 获取获取旋转变换后的left,top
     * */
    getTransformPoint() {
      const newLeftPoint = this.getCenter(
        { x: this.cropperInfo.left + this.imgData.cropBox.left, y: this.cropperInfo.top + this.imgData.cropBox.top },
        {
          x: this.cropperInfo.left + this.cropperInfo.width / 2,
          y: this.cropperInfo.top + this.cropperInfo.height / 2
        },
        this.imgRotate
      )
      const center = this.getCenter(
        {
          x: this.cropperInfo.left + this.imgData.cropBox.left + this.imgData.cropBox.width / 2,
          y: this.cropperInfo.top + this.imgData.cropBox.top + this.imgData.cropBox.height / 2
        },
        {
          x: this.cropperInfo.left + this.cropperInfo.width / 2,
          y: this.cropperInfo.top + this.cropperInfo.height / 2
        },
        this.imgRotate)
      const newCoordinate = this.getCenter(
        { x: newLeftPoint.x, y: newLeftPoint.y },
        { x: center.x, y: center.y },
        -this.imgRotate
      )
      return newCoordinate
    },
    getCenter(point, center, rotate) {
      const deg = Math.PI / 180 * rotate
      const newX = center.x + (point.x - center.x) * Math.cos(deg) - (point.y - center.y) * Math.sin(deg)
      const newY = center.y + (point.x - center.x) * Math.sin(deg) + (point.y - center.y) * Math.cos(deg)
      return {
        x: newX,
        y: newY
      }
    },
    getStyle(styleObj) {
      const needUnitStr = ['width', 'height']
      const style = {}
      for (const key in styleObj) {
        if (needUnitStr.includes(key)) {
          style[key] = styleObj[key] + 'px'
        } else if (key !== 'left' && key !== 'top') {
          style[key] = styleObj[key]
        }
      }
      style.transform = `translate(${styleObj.left}px, ${styleObj.top}px)`
      return style
    },
    setImgData() {
      this.imgData.contain = {
        width: this.cropperInfo.width,
        height: this.cropperInfo.height,
        left: this.cropperInfo.left,
        top: this.cropperInfo.top
      }
      this.imgData.canvas = {
        width: this.imgInfo.width * this.imgInfo.scaleX,
        height: this.imgInfo.height * this.imgInfo.scaleY,
        left: this.imgInfo.left,
        top: this.imgInfo.top,
        flipX: this.imgInfo.flipX,
        flipY: this.imgInfo.flipY
      }
      this.imgData.cropBox = {
        width: this.cropperInfo.width,
        height: this.cropperInfo.height,
        top: 0,
        left: 0
      }
      this.imgData.img = {
        w: this.maxCanvasInfo.width,
        h: this.maxCanvasInfo.height
      }
      this.updateMoveRect()
      const point = {
        x: this.imgData.canvas.width / 2 - this.imgData.cropBox.width / 2 + this.imgInfo.left,
        y: this.imgData.canvas.height / 2 - this.imgData.cropBox.height / 2 + this.imgInfo.top
      }
      const newPoint = this.rotatePoint(point.x, point.y, this.imgRotate)
      this.showRect = {
        ...this.showRect,
        x: newPoint.x,
        y: newPoint.y,
        w: this.imgData.canvas.width,
        h: this.imgData.canvas.height,
        r: this.imgRotate
      }

      this.maskRect = {
        w: this.imgData.cropBox.width,
        h: this.imgData.cropBox.height,
        x: -this.imgData.cropBox.width / 2,
        y: -this.imgData.cropBox.height / 2,
        oldX: -this.imgData.cropBox.width / 2,
        oldY: -this.imgData.cropBox.height / 2
      }

      const newData = this.checkRange()
      this.updateShowRect({ left: newData[0], top: newData[1], width: newData[2], height: newData[3] })
      console.log(JSON.stringify(this.showRect), JSON.stringify(this.maskRect))
    },
    /**
     * crop-box 显示区图片移动
     * */
    handleCanvasDown(e) {
      const parentPosition = document.getElementById(this.parentId).getBoundingClientRect()
      const ex = e.pageX - parentPosition.x - parentPosition.width / 2
      const ey = e.pageY - parentPosition.y - parentPosition.height / 2
      const { x, y } = this.showRect

      const move = moveE => {
        this.showLine = true
        moveE.stopPropagation()
        moveE.preventDefault()
        const currX = moveE.pageX - parentPosition.x - parentPosition.width / 2
        const currY = moveE.pageY - parentPosition.y - parentPosition.height / 2
        const newPoint = this.rotatePoint(currX - ex, currY - ey, this.imgRotate)
        this.showRect.x = x + newPoint.x
        this.showRect.y = y + newPoint.y
      }
      const up = () => {
        this.showLine = false
        const newPoint = this.checkRange()
        this.updateShowRect({ left: newPoint[0], top: newPoint[1], width: newPoint[2], height: newPoint[3] })
        document.removeEventListener('mousemove', move, true)
        document.removeEventListener('mouseup', up, true)
      }
      document.addEventListener('mousemove', move, true)
      document.addEventListener('mouseup', up, true)
      return true
    },
    /**
     * 框缩放显示区的图片
     * */
    handleDown(e) {
      const cropperAction = e.target.dataset.cropperAction
      // const notDrag = ['move', 'n', 'e', 'w', 's']
      const notDrag = ['move']
      if (cropperAction && notDrag.indexOf(cropperAction) === -1) {
        const hasT = /n/.test(cropperAction)
        const hasB = /s/.test(cropperAction)
        const hasL = /w/.test(cropperAction)
        const hasR = /e/.test(cropperAction)

        const parentPosition = document.getElementById(this.parentId).getBoundingClientRect()
        const ex = e.pageX - parentPosition.x
        const ey = e.pageY - parentPosition.y
        const { x: mX, y: mY, w: mW, h: mH } = JSON.parse(JSON.stringify(this.maskRect))

        const move = (moveE) => {
          this.showLine = true
          const moveX = moveE.pageX - parentPosition.x
          const moveY = moveE.pageY - parentPosition.y

          const offsetY = moveY - ey
          const offsetX = moveX - ex

          this.maskRect.oldX = this.maskRect.x
          this.maskRect.oldY = this.maskRect.y
          const scale = offsetY / mH
          if (cropperAction.length === 2) {
            if (hasT && hasL) {
              this.maskRect.x = mX + scale * mW
              this.maskRect.y = mY + scale * mH
              this.maskRect.w = mW - scale * mW
              this.maskRect.h = mH - scale * mH
            }

            if (hasT && hasR) {
              this.maskRect.y = mY + scale * mH
              this.maskRect.w = mW - scale * mW
              this.maskRect.h = mH - scale * mH
            }

            if (hasB && hasL) {
              this.maskRect.x = mX - scale * mW
              this.maskRect.w = mW + scale * mW
              this.maskRect.h = mH + scale * mH
            }

            if (hasR && hasB) {
              this.maskRect.w = mW + scale * mW
              this.maskRect.h = mH + scale * mH
            }
          } else {
            if (this.type) {
              if (hasT) {
                const scale = offsetY / mH
                this.maskRect.y = mY + scale * mH
                this.maskRect.h = mH - scale * mH
                this.maskRect.w = mW - scale * mW
                this.maskRect.x = mX + scale * mW / 2
              }
              if (hasB) {
                const scale = offsetY / mH
                this.maskRect.h = mH + scale * mH
                this.maskRect.w = mW + scale * mW
                this.maskRect.x = mX - scale * mW / 2
              }
              if (hasL) {
                const scale = offsetX / mW
                this.maskRect.x = mX + scale * mW
                this.maskRect.w = mW - scale * mW
                this.maskRect.h = mH - scale * mH
                this.maskRect.y = mY + scale * mH / 2
              }
              if (hasR) {
                const scale = offsetX / mW
                this.maskRect.w = mW + scale * mW
                this.maskRect.h = mH + scale * mH
                this.maskRect.y = mY - scale * mH / 2
              }
            } else {
              if (hasT) {
                const scale = offsetY / mH
                this.maskRect.y = mY + scale * mH
                this.maskRect.h = mH - scale * mH
              }
              if (hasB) {
                const scale = offsetY / mH
                this.maskRect.h = mH + scale * mH
              }
              if (hasL) {
                const scale = offsetX / mW
                this.maskRect.x = mX + scale * mW
                this.maskRect.w = mW - scale * mW
              }
              if (hasR) {
                const scale = offsetX / mW
                this.maskRect.w = mW + scale * mW
              }
            }
          }
        }
        const up = () => {
          this.showLine = false
          document.removeEventListener('mousemove', move)
          document.removeEventListener('mouseup', up)

          if (this.type) {
            const newPoint = this.getMaskRect()
            const zoom = newPoint.w / this.maskRect.w
            const rotatePoint = this.rotatePoint(
              this.maskRect.x + this.maskRect.w / 2,
              this.maskRect.y + this.maskRect.h / 2,
              this.imgRotate
            )

            const offPoint = {
              x: (this.showRect.x - rotatePoint.x) * zoom,
              y: (this.showRect.y - rotatePoint.y) * zoom
            }
            const newRect = this.getRectByRect(newPoint.w, newPoint.h)

            this.moveRect = {
              minX: newRect.x,
              minY: newRect.y,
              maxX: newRect.x + newRect.w,
              maxY: newRect.y + newRect.h
            }

            const { x, y, w, h, r, sV, sH } = this.showRect
            const offX = offPoint.x - x
            const offY = offPoint.y - y
            const offW = w * zoom - w
            const offH = h * zoom - h
            const range = this.checkRange({
              ...offPoint,
              w: w * zoom,
              h: h * zoom,
              r,
              sV,
              sH
            })
            const newOffsetData = [
              offX + range[0],
              offY + range[1],
              offW + range[2],
              offH + range[3]
            ]
            this.setData(newPoint)
            this.$nextTick(() => {
              this.updateShowRect({ left: newOffsetData[0], top: newOffsetData[1], width: newOffsetData[2], height: newOffsetData[3] })
            })
          } else {
            const { left, top } = this.imgData.contain
            const newPoint = this.getMaskRect()

            this.imgData.contain = {
              width: newPoint.w,
              height: newPoint.h,
              left: (this.maxCanvasInfo.width - newPoint.w) / 2,
              top: (this.maxCanvasInfo.height - newPoint.h) / 2
            }
            const zoom = newPoint.w / this.maskRect.w
            this.maskRect.x += this.imgData.contain.left - left
            this.maskRect.y += this.imgData.contain.top - top
            const rotatePoint = this.rotatePoint(
              this.maskRect.x + this.maskRect.w / 2,
              this.maskRect.y + this.maskRect.h / 2,
              this.imgRotate)

            const rotatePoint1 = this.rotatePoint(
              this.imgData.contain.left - left,
              this.imgData.contain.top - top,
              this.imgRotate)

            this.showRect.x += rotatePoint1.x
            this.showRect.y += rotatePoint1.y
            const offPoint = {
              x: (this.showRect.x - rotatePoint.x) * zoom,
              y: (this.showRect.y - rotatePoint.y) * zoom
            }
            const newRect = this.getRectByRect(newPoint.w, newPoint.h)

            this.moveRect = {
              minX: newRect.x,
              minY: newRect.y,
              maxX: newRect.x + newRect.w,
              maxY: newRect.y + newRect.h
            }

            const { x, y, w, h, r, sV, sH } = this.showRect
            const offX = offPoint.x - x
            const offY = offPoint.y - y
            const offW = w * zoom - w
            const offH = h * zoom - h
            const range = this.checkRange({
              ...offPoint,
              w: w * zoom,
              h: h * zoom,
              r,
              sV,
              sH
            })
            const newOffsetData = [
              offX + range[0],
              offY + range[1],
              offW + range[2],
              offH + range[3]
            ]
            this.setData(newPoint)
            this.$nextTick(() => {
              this.updateShowRect({ left: newOffsetData[0], top: newOffsetData[1], width: newOffsetData[2], height: newOffsetData[3] })
            })
          }
        }
        document.addEventListener('mousemove', move)
        document.addEventListener('mouseup', up)
      }
    },
    setData(newPoint) {
      const { x, y } = this.maskRect
      this.maskRect = {
        x: newPoint.x,
        y: newPoint.y,
        w: newPoint.w,
        h: newPoint.h,
        oldX: x,
        oldY: y
      }
    },
    /**
     * 获取旋转指定角度后的rect
     * @param  {[type]} options rect
     * @param  {[type]} angle   旋转角度
     * @return {[type]}
     */
    transform(options, angle) {
      const x = options.x
      const y = options.y
      const width = options.width
      const height = options.height

      const r = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)) / 2
      const a = Math.round(Math.atan(height / width) * 180 / Math.PI)
      const tlbra = 180 - angle - a
      const trbla = a - angle
      const ta = 90 - angle
      const ra = angle

      const halfWidth = width / 2
      const halfHeight = height / 2

      const middleX = x + halfWidth
      const middleY = y + halfHeight

      const topLeft = {
        x: middleX + r * Math.cos(tlbra * Math.PI / 180),
        y: middleY - r * Math.sin(tlbra * Math.PI / 180)
      }
      const top = {
        x: middleX + halfHeight * Math.cos(ta * Math.PI / 180),
        y: middleY - halfHeight * Math.sin(ta * Math.PI / 180)
      }
      const topRight = {
        x: middleX + r * Math.cos(trbla * Math.PI / 180),
        y: middleY - r * Math.sin(trbla * Math.PI / 180)
      }
      const right = {
        x: middleX + halfWidth * Math.cos(ra * Math.PI / 180),
        y: middleY + halfWidth * Math.sin(ra * Math.PI / 180)
      }
      const bottomRight = {
        x: middleX - r * Math.cos(tlbra * Math.PI / 180),
        y: middleY + r * Math.sin(tlbra * Math.PI / 180)
      }
      const bottom = {
        x: middleX - halfHeight * Math.sin(ra * Math.PI / 180),
        y: middleY + halfHeight * Math.cos(ra * Math.PI / 180)
      }
      const bottomLeft = {
        x: middleX - r * Math.cos(trbla * Math.PI / 180),
        y: middleY + r * Math.sin(trbla * Math.PI / 180)
      }
      const left = {
        x: middleX - halfWidth * Math.cos(ra * Math.PI / 180),
        y: middleY - halfWidth * Math.sin(ra * Math.PI / 180)
      }
      const minX = Math.min(topLeft.x, topRight.x, bottomRight.x, bottomLeft.x)
      const maxX = Math.max(topLeft.x, topRight.x, bottomRight.x, bottomLeft.x)
      const minY = Math.min(topLeft.y, topRight.y, bottomRight.y, bottomLeft.y)
      const maxY = Math.max(topLeft.y, topRight.y, bottomRight.y, bottomLeft.y)
      return {
        point: [topLeft, top, topRight, right, bottomRight, bottom, bottomLeft, left],
        width: maxX - minX,
        height: maxY - minY,
        left: minX,
        right: maxX,
        top: minY,
        bottom: maxY
      }
    },
    updateDate(type, { width, height, left, top }) {
      if (type === 'canvas') {
        this.imgData.canvas = {
          left,
          top,
          width,
          height
        }
      }
      if (type === 'cropBox') {
        this.imgData.cropBox = {
          left,
          top,
          width,
          height
        }
      }
    },
    updateMoveRect() {
      const newRect = this.getMoveRect()
      this.moveRect = {
        minX: newRect.x,
        minY: newRect.y,
        maxX: newRect.x + newRect.w,
        maxY: newRect.y + newRect.h
      }
    },
    getMoveRect() {
      const w = this.imgData.cropBox.width
      const h = this.imgData.cropBox.height
      return this.getRectByRect(w, h)
    },
    updateShowRect({ left, top, width, height }) {
      this.showRect = {
        ...this.showRect,
        x: this.showRect.x + left,
        y: this.showRect.y + top,
        w: this.showRect.w + width,
        h: this.showRect.h + height,
        r: this.imgRotate
      }
    },
    rotatePoint(x, y, angle) {
      const a = Math.sqrt(x * x + y * y)
      const r1 = Math.atan2(x, y)
      const r2 = angle * Math.PI / 180 + r1
      return {
        x: a * Math.sin(r2),
        y: a * Math.cos(r2)
      }
    },
    /**
     * 检查图片是否在可移动范围内
     * @param showRect
     * @private
     * @return    坐标偏移量
     */
    checkRange(showRect = this.showRect) {
      let { x: cx, y: cy } = showRect
      const { w: cw, h: ch } = showRect
      cx -= cw / 2
      cy -= ch / 2
      let { minX, minY, maxX, maxY } = this.moveRect
      minX = minX || 0
      minY = minY || 0
      maxX = maxX || 0
      maxY = maxY || 0
      let nx = cx
      let ny = cy
      let nw = cw
      let nh = ch
      let rl = this.getPhotoByRangeLocation([cx, cy, cw, ch])
      // console.log(rl, this.showRect, this.moveRect, 'checkRange===================')
      const imgOff = cw / ch
      if (rl[4] <= 0) {
        nw = maxX - minX
        nh = nw / imgOff
        nx = cx + (cw - nw) / 2
        ny = cy + (ch - nh) / 2
      }
      rl = this.getPhotoByRangeLocation([nx, ny, nw, nh])
      if (rl[5] <= 0) {
        nh = maxY - minY
        nw = nh * imgOff
        nx = cx + (cw - nw) / 2
        ny = cy + (ch - nh) / 2
      }
      rl = this.getPhotoByRangeLocation([nx, ny, nw, nh])
      if (rl[0] > 0) nx -= rl[0]
      if (rl[1] > 0) ny -= rl[1]
      if (rl[2] < 0) nx -= rl[2]
      if (rl[3] < 0) ny -= rl[3]
      const offW = nw - cw
      const offH = nh - ch
      // console.log(offW, offH, nx, cx, ny, cy)
      return [
        nx - cx + offW / 2,
        ny - cy + offH / 2,
        offW,
        offH
      ]
    },
    getPhotoByRangeLocation(newLocation) {
      let { x, y, w, h } = this.showRect
      const { minX, minY, maxX, maxY } = this.moveRect
      if (newLocation) {
        [x, y, w, h] = newLocation
      }
      return [
        x - (minX || 0),
        y - (minY || 0),
        x + w - (maxX || 0),
        y + h - (maxY || 0),
        w - (maxX || 0) + (minX || 0),
        h - (maxY || 0) + (minY || 0)
      ]
    },
    /**
     * 计算裁剪框矩形
     */
    getMaskRect() {
      const k1 = this.maskRect.w / this.maskRect.h
      const k2 = this.imgData.img.w / this.imgData.img.h
      let w
      let h
      if (k1 < k2) {
        h = this.imgData.img.h
        w = k1 * h
      } else {
        w = this.imgData.img.w
        h = w / k1
      }

      return {
        x: -w / 2,
        y: -h / 2,
        w,
        h
      }
    },
    /**
     * 将一个正矩形旋转angle度，
     * 计算该矩形的外接正矩形
     * (假设矩形中心为原点)
     * @param w
     * @param h
     */
    getRectByRect(w, h) {
      const angle = this.imgRotate
      if (!(angle / 180)) {
        return { x: -w / 2, y: -h / 2, w, h }
      }
      const p1 = this.rotatePoint(-w / 2, -h / 2, angle)
      const p2 = this.rotatePoint(w / 2, -h / 2, angle)
      const nx = Math.max(Math.abs(p1.x), Math.abs(p2.x))
      const ny = Math.max(Math.abs(p1.y), Math.abs(p2.y))
      return {
        x: -nx,
        y: -ny,
        w: nx + nx,
        h: ny + ny
      }
    }
  }

}
</script>

<style lang="scss" scoped>
.contain {
  direction: ltr;
  font-size: 0;
  line-height: 0;
  position: absolute;

  .wrap-box, .canvas {
    overflow: hidden;
  }

  .canvas-hide {
    display: block;
    height: 100%;
    position: absolute;
    width: 100%;
  }

  .move {
    cursor: move;
    pointer-events: none;
  }

  .modal {
    background-color: #222;
    opacity: 0.7;
  }

  .crop-box, .border-box {
    .view-box {
      display: block;
      height: 100%;
      border: 1px solid #fff;
      box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.3);
      overflow: hidden;
      width: 100%;
    }

    .dashed {
      border: 0 solid #fff;
      display: block;
      opacity: 1;
      position: absolute;
      pointer-events: none;

      &.dashed-h {
        border-bottom-width: 1px;
        border-top-width: 1px;
        height: calc(100% / 3);
        left: 0;
        top: calc(100% / 3);
        width: 100%;
      }

      &.dashed-v {
        border-left-width: 1px;
        border-right-width: 1px;
        height: 100%;
        left: calc(100% / 3);
        top: 0;
        width: calc(100% / 3);
      }
    }

    .face, .line, .point, .border-point {
      display: block;
      height: 100%;
      opacity: 0.1;
      position: absolute;
      width: 100%;
    }

    .face {
      background-color: #fff;
      left: 0;
      top: 0;
    }

    .line {
      &.line-e {
        cursor: ew-resize;
        right: -3px;
        top: 0;
        width: 5px
      }

      &.line-n {
        cursor: ns-resize;
        height: 5px;
        left: 0;
        top: -3px;
      }

      &.line-w {
        cursor: ew-resize;
        left: -3px;
        top: 0;
        width: 5px;
      }

      &.line-s {
        bottom: -3px;
        cursor: ns-resize;
        height: 5px;
        left: 0;
      }
    }

    .border-point {
      width: 14px;
      height: 14px;
      opacity: 1;
      border-radius: 50%;
      background: #fff;
      border: 1px solid #C6C9CF;

      &.border-point-ne {
        cursor: nesw-resize;
        right: -7px;
        top: -7px;
      }

      &.border-point-nw {
        cursor: nwse-resize;
        left: -7px;
        top: -7px;
      }

      &.border-point-se {
        cursor: nwse-resize;
        right: -7px;
        bottom: -7px;
      }

      &.border-point-sw {
        bottom: -7px;
        cursor: nesw-resize;
        left: -7px;
      }
    }

    .point {
      height: 9px;
      opacity: 1;
      width: 9px;
      border: 2px solid #fff;

      &.point-ne {
        cursor: nesw-resize;
        right: -2px;
        top: -2px;
        border-style: solid solid none none;
      }

      &.point-nw {
        cursor: nwse-resize;
        left: -2px;
        top: -2px;
        border-style: solid none none solid;
      }

      &.point-sw {
        bottom: -2px;
        cursor: nesw-resize;
        left: -2px;
        border-style: none none solid solid;
      }

      &.point-se {
        bottom: -2px;
        cursor: nwse-resize;
        right: -2px;
        border-style: none solid solid none;
      }
    }

    .longer {
      position: absolute;
      background: #fff;
      border-radius: 4px;

      &.longer-e {
        cursor: ew-resize;
        height: 22px;
        width: 5px;
        top: 50%;
        right: -2px;
        margin-top: -11px;
      }

      &.longer-n {
        cursor: ns-resize;
        height: 5px;
        width: 22px;
        top: -2px;
        left: 50%;
        margin-left: -11px;
      }

      &.longer-w {
        cursor: ew-resize;
        height: 22px;
        width: 5px;
        top: 50%;
        left: -2px;
        margin-top: -11px;
      }

      &.longer-s {
        cursor: ns-resize;
        height: 5px;
        width: 22px;
        bottom: -2px;
        left: 50%;
        margin-left: -11px;
      }
    }
  }

  .border-box {
    box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.3);
    border: 2px solid #FFFFFF;
  }

  .crop-box {
    outline: rgba(231,233,234,0.7) solid 10000px;
  }
  .wrap-box, .canvas, .border-box, .drag-box, .crop-box, .modal {
    bottom: 0;
    left: 0;
    position: absolute;
    right: 0;
    top: 0;
  }

  img {
    display: block;
    image-orientation: 0deg;
    max-height: none !important;
    max-width: none !important;
    min-height: 0 !important;
    min-width: 0 !important;
    width: 100%;
    height: 100%;
  }
}

.tooltip {
  position: absolute;
  z-index: 9999;
  clear: both;
  cursor: default;
  width: 211px;
  height: 48px;
  background: #444444;
  box-shadow: 0 5px 12px 4px rgba(0, 0, 0, 0.09);
  border-radius: 4px;
  padding: 12px 0;

  &-btn {
    display: inline-block;
    background: none;
    border-right: 1px solid #666;
    color: #fff;
    cursor: pointer;
    outline: 0;
    position: relative;
    white-space: nowrap;
    vertical-align: top;
    text-align: center;
    -webkit-appearance: none;
    width: 67px;
    height: 24px;
    line-height: 24px;
    font-size: 15px;

    &:last-child {
      border: none;
    }
  }
}
</style>

